package cn.liutao.cron;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.liutao.common.enums.OrderEnum;
import cn.liutao.common.utils.ServletUtils;
import cn.liutao.dish.entity.po.DiningTable;
import cn.liutao.dish.mapper.DiningTableMapper;

import cn.liutao.order.entity.po.Order;
import cn.liutao.order.entity.po.OrderBill;
import cn.liutao.order.mapper.OrderBillMapper;
import cn.liutao.order.mapper.OrderMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import lombok.extern.slf4j.Slf4j;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

import static cn.liutao.order.entity.po.table.OrderBillTableDef.ORDER_BILL;
import static cn.liutao.order.entity.po.table.OrderTableDef.ORDER;


/**
 * @author liutao
 * @Description 定时任务
 * @date 2023/11/5
 */
@Slf4j
public class CronService {

    private static volatile CronService instance;
    private OrderMapper orderMapper;
    private DiningTableMapper diningTableMapper;
    private OrderBillMapper orderBillMapper;
    private CronService() {
        orderMapper = ServletUtils.getMapper(OrderMapper.class);
        diningTableMapper = ServletUtils.getMapper(DiningTableMapper.class);
        orderBillMapper = ServletUtils.getMapper(OrderBillMapper.class);
    }

    public static CronService getInstance() {
        if (instance == null) {
            synchronized (CronService.class) {
                if (instance == null) {
                    instance = new CronService();
                }
            }
        }
        return instance;
    }


    public  void createCron(){
        //创建定时任务
        Task task = new Task() {
            @Override
            public void execute() {
                //定时任务具体逻辑
                log.info("执行定时任务，清除超时订单");
                checkOrder();
            }
        };
        CronUtil.schedule("*/30 * * * *",task);
        CronUtil.setMatchSecond(true);
        CronUtil.start();
        log.info("开启定时任务");
    }



    /**
     * 构造执行模式
     * @param startTime
     * @param offsetValue
     * @param chronoUnit
     * @return
     */
    private  String offsetTime(LocalDateTime startTime,int offsetValue,ChronoUnit chronoUnit) {
        LocalDateTime triggerTime  = startTime.plus(offsetValue, ChronoUnit.MINUTES);
        //构造偏移量
        int second = triggerTime.getSecond();
        int minute = triggerTime.getMinute();
        int hour = triggerTime.getHour();
        int day = triggerTime.getDayOfMonth();
        int month = triggerTime.getMonthValue();
        DayOfWeek weekDay = triggerTime.getDayOfWeek();
        String pattern = second+" "+minute+" "+hour+" "+day+" "+month+" "+weekDay;
        return pattern;
    }



    /**
     * 清除订单逻辑
     *
     */
    public void checkOrder(){
        //获取所有待支付订单列表
        QueryWrapper qw = QueryWrapper.create().where(ORDER.STATUS.eq(OrderEnum.ORDER_STATUS_NO_PAY.getIntValue()));
        List<Order> orderList = orderMapper.selectListByQuery(qw);
        if (CollectionUtil.isEmpty(orderList)){
            return;
        }
        //检查各个订单是否超时
        orderList.forEach(order->{
            LocalDateTime outTime = order.getCreateTime().plus(30, ChronoUnit.SECONDS);
            if (LocalDateTime.now().isAfter(outTime)) {
                //超时
                //设置订单过期，修改订单信息类型
                Db.tx(()->{

                    OrderBill orderBill = orderBillMapper.selectOneByQuery(QueryWrapper.create().where(ORDER_BILL.ORDER_NO.eq(order.getOrderNo())));
                    if (order != null) {
                        order.setStatus(OrderEnum.ORDER_STATUS_OVERDUE.getIntValue());
                        orderMapper.update(order);
                    }
                    if (orderBill != null) {
                        orderBill.setStatus(OrderEnum.ORDER_STATUS_OVERDUE.getIntValue());
                        orderBillMapper.update(orderBill);
                    }
                    //释放餐桌资源
                    DiningTable table = diningTableMapper.selectOneById(order.getTableId());
                    Integer usedQuantity = table.getUsedQuantity()==null?0:table.getUsedQuantity();
                    Integer peopleQuantity = order.getPeopleQuantity() == null ? 0 : order.getPeopleQuantity();
                    table.setUsedQuantity(usedQuantity-peopleQuantity);
                    diningTableMapper.update(table);
                    return true;
                });
            }

        });

    }
}
